/*******************************************************************************
 * Copyright 2009 Omnidroid - http://code.google.com/p/omnidroid 
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 *******************************************************************************/
package edu.nyu.cs.omnidroid.app.controller.datatypes;

import edu.nyu.cs.omnidroid.app.controller.util.DataTypeValidationException;

/**
 * Provides data type that can be used to provide text filters.
 */
public class OmniWeather extends DataType {
	// private String value;
	public String temperature;
	public String humidity;
	public String condition;
	public String wind;

	private static final String OmniWeatherOpenTag = "<omniWeather>";
	private static final String OmniWeatherCloseTag = "</omniWeather>";
	private static final String temperatureOpenTag = "<temperature>";
	private static final String temperatureCloseTag = "</temperature>";
	private static final String humidityOpenTag = "<humidity>";
	private static final String humidityCloseTag = "</humidity>";
	private static final String conditionOpenTag = "<condition>";
	private static final String conditionCloseTag = "</condition>";
	private static final String windOpenTag = "<wind>";
	private static final String windCloseTag = "</wind>";


	/* data type name to be stored in db */
//	public static final String DB_NAME = "Weather";
	public static final String DB_NAME_TEMPERATURE = "WeatherTemperature";
	public static final String DB_NAME_CONDITION = "WeatherCondition";
	public static final String DB_NAME_HUMIDITY = "WeatherHumidity";
	public static final String DB_NAME_WIND = "WeatherWind";
	
	
//	public enum Filter implements DataType.Filter {
//		CURRENT_TEMP_ABOVE("above (current)"), CURRENT_TEMP_BELOW(
//				"below (current)"), CURRENT_HUMIDITY_ABOVE(
//				"above (current)"), CURRENT_HUMIDITY_BELOW(
//				"below (current)"), CURRENT_CONDITION_IS(
//				"is (current)"), CURRENT_CONDITION_NOT(
//				"not (current)"), CURRENT_WIND_ABOVE(
//				"speed above (current)"), CURRENT_WIND_BELOW(
//				"speed below (current)");
//
//		public final String displayName;
//
//		Filter(String displayName) {
//			this.displayName = displayName;
//		}
//	}
	
//	public enum ValueFilter implements DataType.Filter {
//		CURRENT_TEMP_ABOVE("above (current)"), CURRENT_TEMP_BELOW(
//				"below (current)"), CURRENT_HUMIDITY_ABOVE(
//				"above (current)"), CURRENT_HUMIDITY_BELOW(
//				"below (current)"), CURRENT_WIND_ABOVE(
//				"speed above (current)"), CURRENT_WIND_BELOW(
//				"speed below (current)");
//
//		public final String displayName;
//
//		ValueFilter(String displayName) {
//			this.displayName = displayName;
//		}
//	}
	
	public enum TemperatureFilter implements DataType.Filter {
		CURRENT_TEMP_ABOVE("above (current)"), CURRENT_TEMP_BELOW(
				"below (current)");
		
		public final String displayName;

		TemperatureFilter(String displayName) {
			this.displayName = displayName;
		}
	}
	
	public enum HumidityFilter implements DataType.Filter {
		CURRENT_HUMID_ABOVE("above (current)"), CURRENT_HUMID_BELOW(
				"below (current)");
		
		public final String displayName;

		HumidityFilter(String displayName) {
			this.displayName = displayName;
		}
	}	
	
	public enum WindFilter implements DataType.Filter {
		CURRENT_WIND_ABOVE("above (current)"), CURRENT_WIND_BELOW(
				"below (current)");
		
		public final String displayName;

		WindFilter(String displayName) {
			this.displayName = displayName;
		}
	}	
	
	public enum ConditionFilter implements DataType.Filter {
				CURRENT_CONDITION_IS(
				"is (current)"), CURRENT_CONDITION_NOT(
				"not (current)");

		public final String displayName;

		ConditionFilter(String displayName) {
			this.displayName = displayName;
		}
	}

	public OmniWeather(String omniWeatherString)
			throws DataTypeValidationException {
		OmniWeather weather = parseOmniWeather(omniWeatherString);

		init(weather);
	}

	public OmniWeather(OmniWeather weather) throws DataTypeValidationException {
		if (weather == null) {
			throw new DataTypeValidationException(
					"Parameter area cannot be null.");
		}
		init(weather);
	}

	public OmniWeather(String temp, String humid, String cond, String win) {
		temperature = temp;
		humidity = humid;
		condition = cond;
		wind = win;
	}

	private void init(OmniWeather weather) {
		temperature = weather.getTemperature();
		humidity = weather.getHumidity();
		condition = weather.getCondition();
		wind = weather.getWind();
	}

	private static OmniWeather parseOmniWeather(String omniWeatherString)
			throws DataTypeValidationException {
		final DataTypeValidationException validationFailed = new DataTypeValidationException(
				"String is not an OmniWeather.");

		// Parse OmniWeather
		String OmniWeatherBody = parseStringValue(omniWeatherString,
				OmniWeatherOpenTag, OmniWeatherCloseTag, validationFailed);

		// Parse temperature
		String strtemperature = parseStringValue(OmniWeatherBody,
				temperatureOpenTag, temperatureCloseTag, validationFailed);

		// Parse humidity
		String strhumidity = parseStringValue(OmniWeatherBody, humidityOpenTag,
				humidityCloseTag, validationFailed);

		// Parse condition
		String strcondition = parseStringValue(OmniWeatherBody,
				conditionOpenTag, conditionCloseTag, validationFailed);

		// Parse wind
		String strwind = parseStringValue(OmniWeatherBody, windOpenTag,
				windCloseTag, validationFailed);

		// create and return OmniWeather object
		return new OmniWeather(strtemperature, strhumidity, strcondition,
				strwind);
	}

	private static String parseStringValue(String omniWeatherString,
			String omniweatheropentag2, String omniweatherclosetag2,
			DataTypeValidationException validationFailed) {
		return null;
	}

//	/**
//	 * 
//	 * @param str
//	 *            the filter name.
//	 * @return Filter
//	 * @throws IllegalArgumentException
//	 *             when the filter with the given name does not exist.
//	 */
//	public static ValueFilter getValueFilterFromString(String str)
//			throws IllegalArgumentException {
//		return ValueFilter.valueOf(str.toUpperCase());
//	}
	
	/**
	 * 
	 * @param str
	 *            the filter name.
	 * @return Filter
	 * @throws IllegalArgumentException
	 *             when the filter with the given name does not exist.
	 */
	public static TemperatureFilter getTemperatureFilterFromString(String str)
			throws IllegalArgumentException {
		return TemperatureFilter.valueOf(str.toUpperCase());
	}
	
	/**
	 * ValueFilter
	 * @param str
	 *            the filter name.
	 * @return Filter
	 * @throws IllegalArgumentException
	 *             when the filter with the given name does not exist.
	 */
	public static HumidityFilter getHumidityFilterFromString(String str)
			throws IllegalArgumentException {
		return HumidityFilter.valueOf(str.toUpperCase());
	}
	
	/**
	 * 
	 * @param str
	 *            the filter name.
	 * @return Filter
	 * @throws IllegalArgumentException
	 *             when the filter with the given name does not exist.
	 */
	public static WindFilter getWindFilterFromString(String str)
			throws IllegalArgumentException {
		return WindFilter.valueOf(str.toUpperCase());
	}

	/**
	 * 
	 * @param str
	 *            the filter name.
	 * @return Filter
	 * @throws IllegalArgumentException
	 *             when the filter with the given name does not exist.
	 */
	public static ConditionFilter getConditionFilterFromString(String str)
			throws IllegalArgumentException {
		return ConditionFilter.valueOf(str.toUpperCase());
	}
	
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.nyu.cs.omnidroid.core.datatypes.DataType#matchFilter(DataType.Filter,
	 * DataType)
	 */
	public boolean matchFilter(DataType.Filter filter, DataType userDefinedValue)
			throws IllegalArgumentException {
		if (!(filter instanceof Filter)) {
			throw new IllegalArgumentException("Invalid filter type '"
					+ filter.toString() + "' provided.");
		}
		if (userDefinedValue instanceof OmniWeather) {
			return matchFilter((Filter) filter, (OmniWeather) userDefinedValue);
		}
		throw new IllegalArgumentException(
				"Matching filter not found for the datatype "
						+ userDefinedValue.getClass().toString() + ". ");
	}

	
	
//	public boolean matchFilter(ValueFilter filter, OmniWeather comparisonValue) {
//		switch (filter) {
//		case CURRENT_TEMP_ABOVE:
//			return (Integer.getInteger(temperature) > Integer
//					.getInteger(comparisonValue.getTemperature()));
//
//		case CURRENT_TEMP_BELOW:
//			return (Integer.getInteger(temperature) < Integer
//					.getInteger(comparisonValue.getTemperature()));
//
//		case CURRENT_HUMIDITY_ABOVE:
//			return (Integer.getInteger(humidity) > Integer
//					.getInteger(comparisonValue.getHumidity()));
//
//		case CURRENT_HUMIDITY_BELOW:
//			return (Integer.getInteger(humidity) < Integer
//					.getInteger(comparisonValue.getHumidity()));
//
//		case CURRENT_WIND_ABOVE:
//			return (Integer.getInteger(wind) > Integer
//					.getInteger(comparisonValue.getWind()));
//
//		case CURRENT_WIND_BELOW:
//			return (Integer.getInteger(wind) < Integer
//					.getInteger(comparisonValue.getWind()));
//
//		default:
//			return false;
//		}
//	}

	public boolean matchFilter(TemperatureFilter filter, OmniWeather comparisonValue) {
		switch (filter) {
		case CURRENT_TEMP_ABOVE:
			return (Integer.getInteger(temperature) > Integer
					.getInteger(comparisonValue.getTemperature()));

		case CURRENT_TEMP_BELOW:
			return (Integer.getInteger(temperature) < Integer
					.getInteger(comparisonValue.getTemperature()));

		default:
			return false;
		}
	}

	
	public boolean matchFilter(HumidityFilter filter, OmniWeather comparisonValue) {
		switch (filter) {
		case CURRENT_HUMID_ABOVE:
			return (Integer.getInteger(humidity) > Integer
					.getInteger(comparisonValue.getHumidity()));

		case CURRENT_HUMID_BELOW:
			return (Integer.getInteger(humidity) < Integer
					.getInteger(comparisonValue.getHumidity()));

		default:
			return false;
		}
	}

	public boolean matchFilter(WindFilter filter, OmniWeather comparisonValue) {
		switch (filter) {
		case CURRENT_WIND_ABOVE:
			return (Integer.getInteger(humidity) > Integer
					.getInteger(comparisonValue.getHumidity()));

		case CURRENT_WIND_BELOW:
			return (Integer.getInteger(humidity) < Integer
					.getInteger(comparisonValue.getHumidity()));

		default:
			return false;
		}
	}	
	
	public boolean matchFilter(ConditionFilter filter, OmniWeather comparisonValue) {
		switch (filter) {
		case CURRENT_CONDITION_IS:

		case CURRENT_CONDITION_NOT:

		default:
			return false;
		}
	}	
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.nyu.cs.omnidroid.core.datatypes.DataType#validateUserDefinedValue
	 * (java.lang.String, java.lang.String)
	 */
	public static void validateUserDefinedValue(DataType.Filter filter,
			String userInput) throws DataTypeValidationException,
			IllegalArgumentException {
		if (!(filter instanceof Filter)) {
			throw new IllegalArgumentException("Invalid filter type '"
					+ filter.toString() + "' provided.");
		}
		if (userInput == null) {
			throw new DataTypeValidationException(
					"The user input cannot be null.");
		}
	}

	/**
	 * Indicates whether or not the given filter is supported by the data type.
	 * 
	 * @param filter
	 * @return true if the filter is supported, false otherwise.
	 */
	public static boolean isValidFilter(String filter) {
		try {
			getFilterFromString(filter);
		} catch (IllegalArgumentException e) {
			return false;
		}
		return true;
	}

	public String getTemperature() {
		return temperature;
	}

	public void setTemperature(String temperature) {
		this.temperature = temperature;
	}

	public String getHumidity() {
		return humidity;
	}

	public void setHumidity(String humidity) {
		this.humidity = humidity;
	}

	public String getCondition() {
		return condition;
	}

	public void setCondition(String condition) {
		this.condition = condition;
	}

	public String getWind() {
		return wind;
	}

	public void setWind(String wind) {
		this.wind = wind;
	}

	@Override
	public String getValue() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String toString() {
		return OmniWeatherOpenTag + temperatureOpenTag + temperature
				+ temperatureCloseTag + humidityOpenTag + humidity
				+ humidityCloseTag + conditionOpenTag + condition
				+ conditionCloseTag + windOpenTag + wind + windCloseTag
				+ OmniWeatherCloseTag;

	}
}
